home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
general
/
modelers
/
geomview
/
source.lha
/
Geomview
/
src
/
bin
/
ginsu
/
clip.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-17
|
13KB
|
582 lines
#include "clip.h"
/* Clipper 1.0 */
/* by Daeron */
/*****************************************************************************/
void err_msg(char *errmsg)
{
fprintf(stderr,"%s\n",errmsg);
exit(1);
}
/*****************************************************************************/
/* Class initializers */
vertex::vertex()
{
x=0;y=0;z=0;clip=0;vr=0.0;vg=0.0;vb=0.0;num=0;next=NULL;
}
vertex_list::vertex_list()
{
numvtx=0;head=NULL;ptype=0;
}
pvtx::pvtx()
{
num=0;next=NULL;
}
polyvtx_list::polyvtx_list()
{
numvtx=0;head=NULL;
}
poly::poly()
{
numvtx=0;me=NULL;next=NULL;clipped=0;
}
poly_list::poly_list()
{
numpoly=0;head=NULL;ptype=0;
}
/*****************************************************************************/
void vertex_list::clip_vertex(int argc,char *argv[])
{
double tmp,tmp2;
if (!strcmp(argv[3],"-g")) side=1;
else if (!strcmp(argv[3],"-l")) side=0;
else err_msg("Usage: clip <filename> <outfile> -[gl] #a #b #c #d");
sscanf(argv[4],"%lf",&a);
sscanf(argv[5],"%lf",&b);
sscanf(argv[6],"%lf",&c);
sscanf(argv[7],"%lf",&d);
point = head;
while (point!=NULL)
{
tmp = a*(point->x) + b*(point->y) + c*(point->z);
tmp2 = tmp-d;
if (tmp2<0) tmp2*=(-1.0);
if (tmp2>.00001)
{
if ((tmp<d)&&(side==1))
point->clip=1;
else
if ((tmp>d)&&(side==0))
point->clip=1;
}
point = point->next;
}
}
/*****************************************************************************/
void vertex_list::put_in_array(vertex **vertex_set)
{
int count=0;
point = head;
while (point!=NULL)
{
vertex_set[count] = point;
point=point->next;
count++;
}
}
/*****************************************************************************/
vertex *vertex_list::add_vertex(double x, double y, double z, float vr, float vg, float vb)
{
vertex *temp = head;
head = new vertex;
head->next = temp;
head->x = x; head->y = y; head->z = z;
head->vr = vr; head->vg = vg; head->vb = vb;
head->clip = 0;
return (head);
}
/*****************************************************************************/
int polyvtx_list::find_unclipped_vertex(vertex **vertex_set)
{
pvtx *temp = head;
int brk=0;
point = head;
do
{
brk = vertex_set[point->num]->clip;
if (brk)
point=point->next;
} while ((brk)&&(point!=temp));
if ((point==temp)&&(brk)) return (1);
head = point;
return (0);
}
/*****************************************************************************/
int polyvtx_list::clip_each_vertex(vertex_list *vtxl, vertex **vertex_set)
{
pvtx *temp, *next, *last;
double t,t1,t2,nx,ny,nz;
double x1,y1,z1;
double x2,y2,z2;
float vr1,vg1,vb1;
float vr2,vg2,vb2;
float vr,vg,vb;
double a = vtxl->a, b = vtxl->b, c = vtxl->c, d = vtxl->d;
last = head;
point = head;
//fprintf(stderr,"point: %d\n",point);
point->me = vertex_set[point->num];
//fprintf(stderr,"got here\n");
do
{
next = point->next;
next->me = vertex_set[next->num];
vr1 = vertex_set[point->num]->vr; vg1 = vertex_set[point->num]->vg;
vb1 = vertex_set[point->num]->vb;
vr2 = vertex_set[next->num]->vr; vg2 = vertex_set[next->num]->vg;
vb2 = vertex_set[next->num]->vb;
x1 = vertex_set[point->num]->x; y1 = vertex_set[point->num]->y;
z1 = vertex_set[point->num]->z;
x2 = vertex_set[next->num]->x; y2 = vertex_set[next->num]->y;
z2 = vertex_set[next->num]->z;
if ((!(vertex_set[point->num]->clip))&&(vertex_set[next->num]->clip))
{
t1 = (d - a*x1 - b*y1 - c*z1);
t2 = a*(x2 - x1) + b*(y2 - y1) + c*(z2 - z1);
if (t2!=0.0)
{
t = t1 / t2;
nx = x1 + t*(x2 - x1); ny = y1 + t*(y2 - y1); nz = z1 + t*(z2 - z1);
vr = vr1 + t*(vr2 - vr1); vg = vg1 + t*(vg2 - vg1); vb = vb1 + t*(vb2 - vb1);
temp = new pvtx;
temp->me = vtxl->add_vertex(nx,ny,nz,vr,vg,vb);
numvtx++;
temp->next = next;
point->next = temp;
last = temp;
point = next;
next = point->next;
}
else
{
last = point;
point = next;
next = point->next;
vertex_set[point->num]->clip = 0;
}
}
else if ((vertex_set[point->num]->clip)&&(vertex_set[next->num]->clip))
{
/*t2 = a*(x2-x1) + b*(y2-y1) + c*(z2-z1);
if (t2!=0.0)
{*/
last->next = next;
delete point;
numvtx--;
point = next;
next = point->next;
/*}
else
{
printf("AAAA!\n");
last = point;
point = next;
next = point->next;
}*/
}
else if ((vertex_set[point->num]->clip)&&(!(vertex_set[next->num]->clip)))
{
t1 = (d - a*x1 - b*y1 - c*z1);
t2 = a*(x2 - x1) + b*(y2 - y1) + c*(z2 - z1);
if (t2!=0.0)
{
t = t1/t2;
nx = x1 + t*(x2 - x1); ny = y1 + t*(y2 - y1); nz = z1 + t*(z2 - z1);
vr = vr1 + t*(vr2 - vr1); vg = vg1 + t*(vg2 - vg1); vb = vb1 + t*(vb2 - vb1);
temp = new pvtx;
temp->me = vtxl->add_vertex(nx,ny,nz,vr,vg,vb);
temp->next = next;
last->next = temp;
delete point;
last = temp;
point = next;
next = point->next;
}
else
{
last = point;
vertex_set[point->num]->clip = 0;
point = next;
next = point->next;
}
}
else
{
last=point;
point=next;
next=point->next;
}
} while (point!=head);
return numvtx;
}
/*****************************************************************************/
void poly::clip_poly(vertex_list *vtxl, vertex **vertex_set)
{
clipped = me->find_unclipped_vertex(vertex_set);
if (clipped) return;
numvtx = me->clip_each_vertex(vtxl,vertex_set);
}
/*****************************************************************************/
void poly_list::clip_polys(vertex_list *vtxl)
{
vertex **vertex_set;
vertex_set = new vertex*[vtxl->numvtx];
vtxl->put_in_array(vertex_set);
point = head;
while (point!=NULL)
{
point->clip_poly(vtxl,vertex_set);
point=point->next;
}
}
/*****************************************************************************/
void vertex::read_vertex(int count, FILE *fin)
{
char c;
fscanf(fin,"%lf %lf %lf",&x,&y,&z);
//fprintf(stderr,"%lf %lf %lf\n",x,y,z);
vr=1.0;vg=1.0;vb=1.0;
c = ' ';
while (!feof(fin) && c!='\n')
c = (char)fgetc(fin);
num=count;
}
/*****************************************************************************/
void vertex::read_cvertex(int count, FILE *fin)
{
char c;
fscanf(fin,"%lf %lf %lf %f %f %f",&x,&y,&z,&vr,&vg,&vb);
if (vr>1.0) vr/=255.0;
if (vg>1.0) vg/=255.0;
if (vb>1.0) vb/=255.0;
if ((vr<0.0)||(vr>1.0)) vr=0.0;
if ((vg<0.0)||(vg>1.0)) vg=0.0;
if ((vb<0.0)||(vb>1.0)) vb=0.0;
//fprintf(stderr,"%lf %lf %lf\n",x,y,z);
c = ' ';
while (!feof(fin) && c!='\n')
c = (char)fgetc(fin);
num=count;
}
/*****************************************************************************/
void vertex::read_cnvertex(int count, FILE *fin)
{
char c;
float dm;
fscanf(fin,"%lf %lf %lf %f %f %f %f %f %f",&x,&y,&z,&dm,&dm,&dm,&vr,&vg,&vb);
if (vr>1.0) vr/=255.0;
if (vg>1.0) vg/=255.0;
if (vb>1.0) vb/=255.0;
if ((vr<0.0)||(vr>1.0)) vr=0.0;
if ((vg<0.0)||(vg>1.0)) vg=0.0;
if ((vb<0.0)||(vb>1.0)) vb=0.0;
//fprintf(stderr,"%lf %lf %lf\n",x,y,z);
c = ' ';
while (!feof(fin) && c!='\n')
c = (char)fgetc(fin);
num=count;
}
/*****************************************************************************/
void vertex_list::read_vertices(int numvx, FILE *fin)
{
int count;
vertex *old;
numvtx = numvx;
point = new vertex;
if (ptype==0)
point->read_vertex(0,fin);
else if (ptype==1)
point->read_cvertex(0,fin);
else if (ptype==2)
point->read_cnvertex(0,fin);
head = point;
old = point;
for (count=1;count<numvtx;count++)
{
point = new vertex;
old->next = point;
if (ptype==0)
point->read_vertex(count,fin);
else if (ptype==1)
point->read_cvertex(count,fin);
else if (ptype==2)
point->read_cnvertex(count,fin);
old = point;
}
point->next = NULL;
}
/*****************************************************************************/
void pvtx::read_pvtx(FILE *fin)
{
fscanf(fin," %d",&num);
//fprintf(stderr," %d",num);
}
/*****************************************************************************/
void polyvtx_list::read_polyvtx(int numvx, FILE *fin)
{
int count;
pvtx *old;
//char temp;
numvtx = numvx;
point = new pvtx;
point->read_pvtx(fin);
head = point;
old = point;
for (count=1;count<numvtx;count++)
{
point = new pvtx;
old->next = point;
point->read_pvtx(fin);
old = point;
}
point->next = head;
}
/*****************************************************************************/
void poly::read_poly(FILE *fin)
{
char temp;
fscanf(fin,"%d",&numvtx);
//fprintf(stderr,"%d",numvtx);
me = new polyvtx_list;
me->read_polyvtx(numvtx,fin);
r=1.0;g=1.0;b=1.0;
fscanf(fin,"%c",&temp);
if (temp!='\n')
{
fscanf(fin,"%f %f %f",&r,&g,&b);
fscanf(fin,"%c",&temp);
while ((temp!='\n')&&(!feof(fin)))
fscanf(fin,"%c",&temp);
}
}
/*****************************************************************************/
void poly_list::read_polys(int numpl, FILE *fin)
{
int count;
poly *old;
numpoly = numpl;
point = new poly;
point->read_poly(fin);
head = point;
old = point;
for (count=1;count<numpoly;count++)
{
point = new poly;
old->next = point;
point->read_poly(fin);
old = point;
}
point->next = NULL;
}
/*****************************************************************************/
void vertex_list::refresh_vertex_list()
{
int count = 0;
point = head;
while (point!=NULL)
{
if (!(point->clip))
{
point->num = count;
count++;
}
point=point->next;
}
numvtx=count;
}
/*****************************************************************************/
void poly_list::refresh_poly_list()
{
int count = 0;
point = head;
while (point!=NULL)
{
if (!(point->clipped))
count++;
point=point->next;
}
numpoly=count;
}
/*****************************************************************************/
void load_off_file(poly_list *polyhedron, vertex_list *polyvertex,
int argc, char *argv[], char *storename)
{
FILE *fin;
char toss[256];
char c;
int vrtx,face,edge;
if ((argc<8)||(argc>8)) err_msg("Usage: clip <filename> <outfile> -[gl] #a #b #c #d");
if (!(fin=fopen(argv[1],"r"))) err_msg("Could not open input file.");
c = ' ';
while ((c!='=')&&(!feof(fin)))
c=(char)fgetc(fin);
fscanf(fin,"%s\n",toss);
sprintf(storename,"%s",argv[2]);
if (strcmp(toss,"OFF")&&strcmp(toss,"NOFF")&&strcmp(toss,"COFF")&&strcmp(toss,"CNOFF")) err_msg("Incorrect file format");
if (!strcmp(toss,"OFF")) polyvertex->ptype=0;
else if (!strcmp(toss,"NOFF")) polyvertex->ptype=0;
else if (!strcmp(toss,"COFF")) polyvertex->ptype=1;
else if (!strcmp(toss,"CNOFF")) polyvertex->ptype=2;
polyhedron->ptype = polyvertex->ptype;
fscanf(fin,"%d %d %d\n",&vrtx,&face,&edge);
if ((vrtx==0)||(face==0)||(edge==0)) err_msg("Bad parameters.");
polyvertex->read_vertices(vrtx,fin);
polyhedron->read_polys(face,fin);
}
/*****************************************************************************/
void vertex_list::write_vertices(FILE *fout)
{
point=head;
if (ptype==0)
{
while(point!=NULL)
{
if (!(point->clip))
fprintf(fout,"\t%lf %lf %lf\n",point->x,point->y,point->z);
point=point->next;
}
}
else
{
while(point!=NULL)
{
if (!(point->clip))
fprintf(fout,"\t%lf %lf %lf %f %f %f 1.0\n",point->x,point->y,point->z,point->vr,point->vg,point->vb);
point=point->next;
}
}
}
/*****************************************************************************/
void polyvtx_list::write_polyvtx(FILE *fout)
{
pvtx *temp;
temp=head;
point=head;
fprintf(fout,"\t%d",numvtx);
do
{
fprintf(fout," %d",point->me->num);
point=point->next;
} while (point!=temp);
}
/*****************************************************************************/
void poly_list::write_polys(FILE *fout)
{
point=head;
while(point!=NULL)
{
if (!(point->clipped))
{
point->me->write_polyvtx(fout);
if (ptype==0)
fprintf(fout," %f %f %f 1.0\n",point->r,point->g,point->b);
else
fprintf(fout,"\n");
}
point=point->next;
}
}
/*****************************************************************************/
void store_off_file(poly_list *polyhedron, vertex_list *polyvertex,
char *storename)
{
FILE *fout;
if (!(fout=fopen(storename,"w"))) err_msg("Couldn\'t save to output file.\n");
if ((polyvertex->ptype)==0)
fprintf(fout,"OFF\n %d %d 1\n",polyvertex->numvtx,polyhedron->numpoly);
else
fprintf(fout,"COFF\n %d %d 1\n",polyvertex->numvtx,polyhedron->numpoly);
polyvertex->write_vertices(fout);
polyhedron->write_polys(fout);
fclose(fout);
}
/*****************************************************************************/
void main_clip(int argc, char *argv[])
{
poly_list polyhedron;
vertex_list polyvertex;
char *storename = new char[256];
load_off_file(&polyhedron,&polyvertex,argc,argv,storename);
polyvertex.clip_vertex(argc,argv);
polyhedron.clip_polys(&polyvertex);
polyvertex.refresh_vertex_list();
polyhedron.refresh_poly_list();
store_off_file(&polyhedron,&polyvertex,storename);
}
/*****************************************************************************/